
/**
 * @warning This file is intended for browser usage only.
 * For Node.js environments, import Image, Audio, Pdf, and Video directly from '@boundaryml/baml'.
 * Example:
 * ```ts
 * // ✅ Browser usage
 * import { Image, Audio, Pdf, Video } from '@boundaryml/baml/browser'
 *
 * // ❌ Don't import these from '@boundaryml/baml' in browser environments
 * import { Image, Audio, Pdf, Video } from '@boundaryml/baml'
 * ```
 */

// Detect if we're in server-side rendering environment
const isSSR = typeof window === 'undefined';

// Create a proxy handler that logs warnings in SSR environment
function createSSRProxyHandler<T extends object>(
  name: string,
): ProxyHandler<T> {
  return {
    get: (target, prop) => {
      if (isSSR) {
        console.warn(
          `Using ${name} from '@boundaryml/baml/browser' in a server-side environment. This will not function properly in SSR.`,
        );
      }
      return (target as Record<string | symbol, unknown>)[prop];
    },
  };
}

{% for media_type in ["Image", "Audio", "Video", "Pdf"] %}
/**
 * Browser-compatible implementation of Baml{{ media_type }}
 */
export class Baml{{ media_type }} {
  private constructor(
    private readonly type: 'url' | 'base64',
    private readonly content: string,
    private readonly mediaType?: string,
  ) {}

  /**
   * Create a Baml{{ media_type }} from a URL
   */
  static fromUrl(url: string, mediaType?: string): Baml{{ media_type }} {
    return new Baml{{ media_type }}('url', url, mediaType)
  }

  /**
   * Create a Baml{{ media_type }} from base64 encoded data
   */
  static fromBase64(mediaType: string, base64: string): Baml{{ media_type }} {
    return new Baml{{ media_type }}('base64', base64, mediaType)
  }

  /**
   * Create a Baml{{ media_type }} from a File object
   */
  static async fromFile(file: File): Promise<Baml{{ media_type }}> {
    return Baml{{ media_type }}.fromBlob(file, file.type)
  }

  /**
   * Create a Baml{{ media_type }} from a Blob object
   */
  static async fromBlob(blob: Blob, mediaType?: string): Promise<Baml{{ media_type }}> {
    const base64 = await new Promise<string>((resolve, reject) => {
      const reader = new FileReader()
      reader.onload = () => resolve(reader.result as string)
      reader.onerror = reject
      reader.readAsDataURL(blob)
    })
    // Remove the data URL prefix to get just the base64 string
    const base64Data = base64.replace(/^data:.*?;base64,/, '')
    return Baml{{ media_type }}.fromBase64(mediaType || blob.type, base64Data)
  }

  /**
   * Create a Baml{{ media_type }} by fetching from a URL
   */
  static async fromUrlToBase64(url: string): Promise<Baml{{ media_type }}> {
    const response = await fetch(url)
    const blob = await response.blob()
    return Baml{{ media_type }}.fromBlob(blob)
  }

  /**
   * Check if the {{ media_type }} is stored as a URL
   */
  isUrl(): boolean {
    return this.type === 'url'
  }

  /**
   * Get the URL of the {{ media_type }} if it's stored as a URL
   * @throws Error if the {{ media_type }} is not stored as a URL
   */
  asUrl(): string {
    if (!this.isUrl()) {
      throw new Error('{{ media_type }} is not a URL')
    }
    return this.content
  }

  /**
   * Get the base64 data and media type if the {{ media_type }} is stored as base64
   * @returns [base64Data, mediaType]
   * @throws Error if the {{ media_type }} is not stored as base64
   */
  asBase64(): [string, string] {
    if (this.type !== 'base64') {
      throw new Error('{{ media_type }} is not base64')
    }
    return [this.content, this.mediaType || '']
  }

  /**
   * Convert the {{ media_type }} to a JSON representation
   */
  toJSON(): { url: string } | { base64: string; media_type: string } {
    if (this.type === 'url') {
      return { url: this.content }
    }
    return {
      base64: this.content,
      media_type: this.mediaType || '',
    }
  }
}

// Create proxied versions that will work in both environments but warn in SSR
const {{ media_type }}Impl = new Proxy(
  Baml{{ media_type }},
  createSSRProxyHandler<typeof Baml{{ media_type }}>('{{ media_type }}'),
);

// Now export everything properly
// First, define the type alias
export type {{ media_type }} = Baml{{ media_type }};
// Then export the implementations
export { {{ media_type }}Impl as {{ media_type }} };
{% endfor %}
